package com.ikingtech.framework.sdk.enums.datasource;

import com.ikingtech.framework.sdk.utils.Tools;
import lombok.RequiredArgsConstructor;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
public enum DatasourceSchemaTypeEnum {

    /**
     * Mysql
     */
    MYSQL("Mysql",
            "com.mysql.cj.jdbc.Driver",
            "jdbc:mysql://{}:{}/mysql?characterEncoding=utf8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai",
            "select SCHEMA_NAME as schema_name from information_schema.schemata",
            "select TABLE_NAME as table_name, TABLE_COMMENT as table_comment from information_schema.tables where table_schema= '{}'",
            "select TABLE_NAME as table_name, COLUMN_NAME as column_name, DATA_TYPE as data_type, CHARACTER_MAXIMUM_LENGTH as character_maximum_length, IS_NULLABLE as is_nullable,COLUMN_KEY as column_key,COLUMN_COMMENT as column_comment from information_schema.columns where table_schema = '{}' and table_name = '{}'"),

    /**
     * POSTGRES
     */
    POSTGRES("Postgres",
            "org.postgresql.Driver",
            "jdbc:postgresql://{}:{}/{}?useUnicode=true&characterEncoding=utf8&reWriteBatchedInserts=true",
            "select DISTINCT(table_schema) as schema_name from information_schema.tables where table_schema != 'pg_catalog' AND table_schema !='information_schema'",
            "SELECT TABLE_NAME as table_name,'' as table_comment FROM information_schema.tables WHERE table_schema = '{}'",
            "SELECT TABLE_NAME as table_name,COLUMN_NAME as column_name,DATA_TYPE as data_type,CHARACTER_MAXIMUM_LENGTH as character_maximum_length,IS_NULLABLE as is_nullable,0 as column_key,'' as column_comment FROM information_schema.columns WHERE table_schema = '{}' and table_name = '{}'"),

    /**
     * ORACLE
     */
    ORACLE("Oracle",
            "oracle.jdbc.driver.OracleDriver",
            "jdbc:oracle:thin:@//{}:{}/{}",
            "SELECT username as schema_name FROM dba_users",
            "SELECT TABLE_NAME as table_name,'' as table_comment FROM all_tables WHERE owner = '{}'",
            "SELECT TABLE_NAME as table_name, COLUMN_NAME as column_name, DATA_TYPE as data_type, TO_NUMBER(DATA_LENGTH) as character_maximum_length, NULLABLE as is_nullable,'' as column_key,'' as column_comment FROM all_tab_columns WHERE owner = '{}' and table_name = '{}'"),

    /**
     * MSSQL_SERVER
     */
    MSSQL_SERVER("SQLServer",
            "com.microsoft.sqlserver.jdbc.SQLServerDriver",
            "jdbc:sqlserver://{}:{};",
            "SELECT name AS schema_name FROM sys.databases","","");

    public final String description;

    public final String driverClassName;

    public final String jdbcUrl;

    public final String schemaQuerySql;

    public final String tableQuerySql;

    public final String fieldQuerySql;

    public String jdbcUrl(String ip, String port, String serviceName, String databaseName) {
        if (MYSQL.equals(this)) {
            return Tools.Str.format(MYSQL.jdbcUrl, ip, port);
        }
        if (POSTGRES.equals(this)) {
            return Tools.Str.format(POSTGRES.jdbcUrl, ip, port, Tools.Str.is(databaseName));
        }
        if (ORACLE.equals(this)) {
            return Tools.Str.format(ORACLE.jdbcUrl, ip, port, serviceName);
        }
        if (MSSQL_SERVER.equals(this)) {
            return Tools.Str.format(MSSQL_SERVER.jdbcUrl, ip, port);
        }
        return null;
    }

    public static String parseHostByJdbcUrl(String databaseType, String jdbcUrl) {
        String urlWithoutPrefix = jdbcUrl.substring(jdbcUrl.indexOf("/") + 2);
        if (MYSQL.name().equals(databaseType)) {
            return urlWithoutPrefix.substring(0, urlWithoutPrefix.indexOf("/"));
        }
        if (POSTGRES.name().equals(databaseType)) {
            return urlWithoutPrefix.substring(0, urlWithoutPrefix.indexOf("?"));
        }
        if (ORACLE.name().equals(databaseType)) {
            return jdbcUrl.substring(jdbcUrl.indexOf("@") + 1);
        }
        if (MSSQL_SERVER.name().equals(databaseType)) {
            return urlWithoutPrefix;
        }
        return null;
    }

    public static DatasourceSchemaTypeEnum valueOfDriverClassName(String driverClassName) {
        for (DatasourceSchemaTypeEnum value : DatasourceSchemaTypeEnum.values()) {
            if (value.driverClassName.equals(driverClassName)) {
                return value;
            }
        }
        return null;
    }
}
